#include <arpa/inet.h>
#include <cstring>
#include <ifaddrs.h>
#include <iostream>
#include <string>
#include <utility>

using namespace std;

// 获取当前 IPv4 地址
string getCurrentIPv4() {
	struct ifaddrs *ifaddr, *ifa;
	if (getifaddrs(&ifaddr) == -1) {
		perror("getifaddrs");
		return "";
	}

	string ip;
	for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == nullptr) {
			continue;
		}

		int family = ifa->ifa_addr->sa_family;
		if (family == AF_INET) {
			void *addr;
			if (family == AF_INET) {
				struct sockaddr_in *ipv4 = (struct sockaddr_in *) ifa->ifa_addr;
				addr                     = &(ipv4->sin_addr);
			}

			char ipstr[INET6_ADDRSTRLEN];
			inet_ntop(family, addr, ipstr, sizeof(ipstr));
			// 排除回环地址
			if (string(ipstr) != "127.0.0.1") {
				ip = ipstr;
				break;
			}
		}
	}

	freeifaddrs(ifaddr);
	return ip;
}

// 解析地址字符串为 IP 和端口
pair<string, int> parseAddress(const string &address) {
	size_t colonPos = address.find(':');
	if (colonPos == string::npos) {
		return {"", 0};
	}
	string ip = address.substr(0, colonPos);
	int port  = stoi(address.substr(colonPos + 1));
	return {ip, port};
}

// IP 字符串转数字
in_addr_t ipStringToNumber(const string &ip) {
	in_addr_t num = inet_addr(ip.c_str());
	if (num == INADDR_NONE) {
		cerr << "Invalid IP address" << endl;
	}
	return num;
}

// IP 数字转字符串
string ipNumberToString(in_addr_t num) {
	struct in_addr addr;
	addr.s_addr = num;
	char ipstr[INET_ADDRSTRLEN];
	inet_ntop(AF_INET, &addr, ipstr, INET_ADDRSTRLEN);
	return ipstr;
}


// g++ -std=c++11 ip.cpp -o ip.exe
int main() {
	// 获取当前 IPv4 地址
	string currentIP = getCurrentIPv4();
	cout << "Current IPv4: " << currentIP << endl;

	// 解析地址字符串
	string address           = "192.168.1.100:8888";
	pair<string, int> parsed = parseAddress(address);
	cout << "Parsed IP: " << parsed.first << ", Port: " << parsed.second << endl;
	// cout << "Parsed IP: " << ip << ", Port: " << port << endl;

	// IP 字符串转数字
	in_addr_t ipNum = ipStringToNumber(parsed.first);
	cout << "IP as number: " << ipNum << endl;

	// IP 数字转字符串
	string ipStr = ipNumberToString(ipNum);
	cout << "Number as IP: " << ipStr << endl;

	return 0;
}
